/**
 * This class embodies the Host authorization panel.
 */
package org.hackystat.ui.sensordatabrowser.client;

import java.util.Date;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * This class embodies the Host authorization panel.
 * @author David J. Nickles
 *
 */
public class HostPanels extends HorizontalPanel implements WindowResizeListener {

  private Boolean sensorbaseStatus;
  private Date sensorbaseTstamp;
  private Label hostLabel;
  private HTML hostPanelFeedback;
  private Image hostPanelImage;
  private Session session;
  private static final String newLineChar = "<br />";
  private Panel statusPanel;
  private Panel settingsPanel;
  private UserPanels userPanels;
  
  /**
   * Construct a valid set of hosts.
   * 
   * @param session the current session attributes
   */
  public HostPanels(Session session) {
    this.session = session;
    
    HorizontalPanel hostSettingsPanel = new HorizontalPanel();
    hostSettingsPanel.setStyleName(Styles.SETTINGSPANELPANESTYLE);
    Label uriLabel = new Label("URI:");
    uriLabel.setStyleName(Styles.EXAMPLELABELSTYLE);
    hostSettingsPanel.add(uriLabel);
    this.hostLabel = new Label("Example: http://hackystat.org:9876/sensorbase");
    this.hostLabel.setStyleName(Styles.EXAMPLELABELSTYLE);
    hostSettingsPanel.add(this.hostLabel);
    RootPanel.get("hostSettingsSlot").add(hostSettingsPanel);
    this.statusPanel = hostSettingsPanel;
    
    HorizontalPanel hostColumns = new HorizontalPanel();
    this.hostPanelImage = new Image(Images.HOST_IMAGE);
    this.hostPanelImage.setStyleName(Styles.STATUSIMAGESTYLE);
    hostColumns.add(this.hostPanelImage);
    VerticalPanel hostRows = new VerticalPanel();
    Label hostLabel2 = new Label("Host");
    hostRows.add(hostLabel2);
    hostLabel2.setStyleName(Styles.SMALLLABELSTYLE);
    this.hostPanelFeedback = new HTML("Sensorbase status.");
    this.hostPanelFeedback.setStyleName(Styles.EXAMPLELABELSTYLE);
    hostRows.add(this.hostPanelFeedback);
    hostColumns.add(hostRows);
    RootPanel.get("hostStatusSlot").add(hostColumns);
    this.settingsPanel = hostColumns;
    
    Window.addWindowResizeListener(this);
    this.setWidth(Integer.toString(Window.getClientWidth() - 34) + Styles.PIXELSUFFIX);
    
    rpcGetHost(); // NOPMD
  }
  
  /**
   * This method returns the host settings panel.
   * @return settings panel.
   */
  public Panel getSettingsPanel() {
    return this.settingsPanel;
  }
  
  /**
   * This method returns the host settings panel.
   * @return status panel.
   */
  public Panel getStatusPanel() {
    return this.statusPanel;
  }
  
  /**
   * This method sets the name of the host uri.
   * @param uri the sensorbase host domain and path
   */
  public void setHost(String uri) {
    this.hostLabel.setText(uri);
    this.session.setSensorbaseHost(uri);
    this.hostPanelFeedback.setText("Properties file located.");
    this.hostPanelImage.setUrl(Images.HOST_IMAGE);
    rpcIsHost();
  }
  
  /**
   * Check with the servlet to get the host name from the properties file.
   */
  private void rpcGetHost() {
    this.hostPanelImage.setUrl(Images.WAIT_IMAGE);
    this.hostPanelFeedback.setText("Searching for the properties file.");
    RPCServiceFactory.getInstance().getService().getHost(new AsyncCallback()
    {
      public void onSuccess(Object result) {
        setHost((String) result);
      }
  
      public void onFailure(Throwable caught) {
        if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
          log(RPCServiceFactory.PRCERRORNAME, "Cannot invoke get host uri property on servlet.");
        } 
        else {
          log(RPCServiceFactory.PRCERRORNAME, caught.toString());
        }
      }
    });
  }
  
  /**
   * This method sets the state of the sensorbase service in the UI.
   * @param state Boolean represents the state of the user valid=true, invalid=false
   */
  public void setHostStatus(Boolean state) {
    this.hostPanelImage.setUrl(Images.HOST_IMAGE);
    this.sensorbaseTstamp = new Date();
    String time = DateTimeFactories.getInstance().getBodyfactory().format(this.sensorbaseTstamp);
    if (state != null && state.booleanValue()) {
      this.sensorbaseStatus = Boolean.TRUE;
      this.hostPanelImage.setUrl(Images.HOST_VALID);
      this.hostPanelFeedback.setText(time + ", Sensorbase service contacted successfully.");
      this.hostPanelFeedback.setStyleName(Styles.VALIDLABELSTYLE);
      this.userPanels = new UserPanels(this.session);
    } 
    else {
      this.sensorbaseStatus = Boolean.FALSE;
      this.hostPanelImage.setUrl(Images.HOST_INVALID);
      this.hostPanelFeedback.setText(time + ", Sensorbase service unavailable.");
      this.hostPanelFeedback.setStyleName(Styles.INVALIDLABELSTYLE);
    }
  }
  
  /**
   * Check with the servlet to see if the host is valid.
   */
  public void rpcIsHost() {
    this.hostPanelFeedback.setHTML("Validating the Sensorbase host is at"
      + newLineChar + "URI: " + this.hostLabel.getText());
    this.hostPanelImage.setUrl(Images.WAIT_IMAGE);
    RPCServiceFactory.getInstance().getService().isHost(this.hostLabel.getText(), 
      new AsyncCallback()
      {
        public void onSuccess(Object result) {
          setHostStatus((Boolean) result);
        }
      
        public void onFailure(Throwable caught) {
          if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
            log(RPCServiceFactory.PRCERRORNAME, "Cannot invoke host validation on servlet.");
          } 
          else {
            log(RPCServiceFactory.PRCERRORNAME, caught.toString());
          }
        }
      });
  }
  
  /**
   * This method returns if the sensorbase service is available.
   * @return true if the sensorbase service has been contacted successfully, false if not.
   */
  public Boolean getSensorbaseStatus() {
    return this.sensorbaseStatus;
  }
  
  /**
   * Log this message in the display.
   * @param header the message header or subject
   * @param body the message body
   */
  private void log(String header, String body) {
    Window.alert(header + " : " + body);
  }
  
  /** 
   * Listens for user resizing of the window.
   * @param width of the adjusted window.
   * @param height of the adjusted window.
   */
  public void onWindowResized(int width, int height) {
    this.setWidth(Integer.toString(width - 34) + Styles.PIXELSUFFIX);
  }
}
